package Monopol;

import java.awt.Color;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import Cards.Card;
import Cards.Card.CardType;
import Cards.Move_card.eGoTo;
import Cards.Money_card;
import Cards.Move_card;
import GameEvents.DiceEvents;
import GameEvents.GameEvents;
import GameEvents.MoveEvents;
import GameEvents.PaymentEvents;
import Monopol.MonopolExceptions.DeletePlayer;
import Monopol.MonopolExceptions.InsufficientFunds;
import Monopol.MonopolExceptions.NoAssets;
import Monopol.MonopolExceptions.PlayerForcedtoQuit;
import Monopol.MonopolExceptions.PlayerQuits;
import Monopol.MonopolExceptions.WrongCardType;
import Monopol.AssetGroups.AllServices;
import Monopol.AssetGroups.AllTransportations;
import Monopol.AssetGroups.State;
import Monopol.MonopolExceptions.MonopolErrors;
import Player.Computer;
import Player.Human;
import Player.Player;
import Square.City;
import Square.Square;
import Square.Square.fixedSquares;
import Utils.Utils;
import XMLParser.MonopolyXML;
import java.util.List;
import java.net.URL;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Level;
import java.util.logging.Logger;
import monopoly.gamemanager.MonopolyGameManager;
import monopoly.gamemanager.MonopolyGameManager.PlayerDetails;
import monopoly.results.EventArrayResult;

/**
 * @author Avia Tam
 * @author Assaf Miron
 *
 */
public class Monopol {

    private ArrayList<Player> players; // A List of all the Players in the Game
    private Square[] squares; // A List of the Squares in the Game
    private ArrayList<Card> warning_cards; // A List of all the Warning Cards
    private ArrayList<Card> surprise_cards; // A List of all Surprise Cards
    public AllServices services; // A Group of All Services
    public AllTransportations transportations; // A Group of All Transportations
    private State[] states; // A Group of All the States
    private Double cashier; // The Total Amount of the Cashier Money
    public Card saved_card; // Saves get out of prison card
    private Integer numOfPlayingPlayers;// Stores the number of player
    public Boolean rollDice = false; //verify if human player wants to throw the dice
    public Boolean automaticDiceRoll;//verify if game uses manual or automatic dice roll
    public String GameName;//contains the game name given by the game creator
    private EventArrayResult EventArrayResult;//stores evetns that happend during the game
    public Timer timer; // used to count time
    public TimeoutTask TimeOutTask;//used to initiate resign proccess
    public Boolean waiting = true;//used to check if timer expired
    // Define Constants
    public final int MIN_NUMBER_OF_PLAYERS = 2;
    public final int MAX_NUMBER_OF_PLAYERS = 6;
    private final Integer MAX_HOUSES = 3;
    private final Integer NUMBER_OF_ALLOWED_AUCTION = 3;
    private final Integer TIMEOUT = 30;
    private Integer eventsIDCounter = 0;
    // Instance
    private static Monopol instance;

    static {
        instance = new Monopol();
    }
    //constractor

    private Monopol() {
    }

    //called from Monopoly game if input was in time
    public void cancelTimer() {
	waiting = false;
	timer.cancel();
    }

    public static Monopol getInstance() {
        return instance;
    }

    public void setEventArrayResult(EventArrayResult Result) {
	this.EventArrayResult = Result;
    }

   public EventArrayResult getEventArrayResult() {
	return EventArrayResult;
    }

   public Integer getEventIDCounter(){
       Integer counter = eventsIDCounter;
       eventsIDCounter++;
       return counter;
   }

    /**
     * Finds The Player From the Player ID and
     * Returns it Only if It has enough Funds (Greater than the Amount)
     * @param playerID The Player ID To Find in the Players Array
     * @param amount The Amount of Money the Plaer Have to Have
     * @return The Player that Has the Money accourding to the Player ID
     */
    public Player getplayer(int playerID, int amount) {
	// Set return Player as Null - No Player
	Player res = null;
	Boolean found = false;
	// Loop the Players Array
	Iterator<Player> iterator = players.iterator();
	while(iterator.hasNext() && !found) {
	    Player player = iterator.next();
	    // Check if the Player has the Requested Player ID
	    if (player.getID().equals(playerID)) {
		// Check if the Player have Funds greater (or Equal) to the Amount Requested
		if (player.getFunds() >= amount) {
		    // We found our Player
		    res = player;
		    // Exit the Loop
		    found = true;
		}
	    }
	}
	// Return the Player - Null if Error
	return res;
    }


    /*
     * timeout task will be called if user didn't replay with answer
     */
    public class TimeoutTask extends TimerTask {

	Integer playerID;//receving player ID

	public TimeoutTask(Integer playerID) {
	    this.playerID = playerID;
	}

	public void run() {
	    try {
		deletePlayer(playerID); //deleteing player since he didn't responed
	    } catch (MonopolErrors ex) {
		Logger.getLogger(Monopol.class.getName()).log(Level.SEVERE, null, ex);
	    }
	    waiting = false;
	    timer.cancel();//kill timer
	}
    }

    /**
     * The Cubes of the Game - 2 Cubes
     * @author Avia Tam
     * @author Assaf Miron
     *
     */
    public class Cubes {

	private Cube[] cubes;
	private boolean isDouble;

	public Cube[] getCubes() {
	    return cubes;
	}

	public boolean isDouble() {
	    return isDouble;
	}

	public Cubes() {
	    super();
	    // Initialize the Cubes Array
	    cubes = new Cube[2];
	    // Initialize Each Cube
	    for (int i = 0; i < 2; i++) {
		cubes[i] = new Cube();
	    }
	}

	/**
	 * Rolls the Dices and updates if the result is a Double or not
	 * @return The Sum of both of the Cubes
	 */
	public Integer rollCubes(Player player) {
	    Integer num1, num2;
	    // Throw the Cubes
	    num1 = cubes[0].throwcube();
	    num2 = cubes[1].throwcube();

	    // Check if its a Double
	    if (num1 == num2) {
		isDouble = true;
	    } else {
		isDouble = false;
	    }


	    // Return the Cubes Result
	    EventArrayResult.addResults(new DiceEvents(GameName, Monopol.getInstance().getEventIDCounter(), TIMEOUT, 7, player.getName(), " Dice Roll", player.getGame_location(), num1, num2));

	    return num1 + num2;
	}

	public Integer setCubes(DiceEvents userDices) {
	    Integer num1, num2;
	    // import dice result
	    num1 = userDices.getFirstDiceResult();
	    num2 = userDices.getSecondDiceResult();
	    // Check if its a Double
	    if (num1 == num2) {
		isDouble = true;
	    } else {
		isDouble = false;
	    }


	    // Return the Cubes Result
	    return num1 + num2;
	}

	@Override
	public String toString() {
	    return cubes[0].value.toString() + ", " + cubes[1].value.toString();
	}
    }

    /**
     * The Main Function of this Class
     * @param args
     */
    public void start(List<PlayerDetails> addplayers, boolean useAutomaticDiceRoll, String GameName) {
	// Initialize the Game
	this.automaticDiceRoll = useAutomaticDiceRoll;
	this.GameName = GameName;
        //init event counter
        eventsIDCounter=new Integer(0);
	// Initialize the Events Array
	EventArrayResult = new EventArrayResult();
	// Initialize the Players Array
	players = new ArrayList<Player>();
	for (PlayerDetails addplayer : addplayers) {
	    if (addplayer.PlayerIsHuman())//if player is human
	    {
		// Create a new Human Player
		Human player = new Human(addplayer.getName(), ((double) addplayer.getAmount()), addplayer.getID());
		// Add the New Player to the Game
		players.add(player);
	    } else {
		// Create a new Computer Player
		Computer player = new Computer(addplayer.getName(), (double) addplayer.getAmount(), addplayer.getID());
		// Add the New Player to the Game
		players.add(player);
	    }
	}
	// Read the Game Squares and Cards
	initGame();

	// Set the Default Amount in the Cashier
	cashier = new Double(100000); // Set to 100K Shekels

	// Add the Start event
	EventArrayResult.addResults(new GameEvents(GameName, Monopol.getInstance().getEventIDCounter(), 1, null, "Game Start ", 0));
	// Plays the game
	try {
	    System.out.println("Starting the Game!");
	    javaplaygame();
	} catch (DeletePlayer e) {
	    // Shouldn't get Here, Player should be Deleted in the Game
	    throw new RuntimeException("Player was not Deleted where it should.");
	}
	System.out.println("Ending the Game");
        System.out.println("the counter size is :"+eventsIDCounter.toString());
	MonopolyGameManager.getInstance().removeGame(GameName);
    }

public synchronized void javaplaygame() throws DeletePlayer {
	// Create a new Variable for the Game Cubes
	Integer gameCubes = null;
	// Create a new Instance of the Cubes
	Cubes cubes = new Cubes();
	// Create a new Variable for the Players left Playing
	numOfPlayingPlayers = players.size();
	try {
	    // Loop until only one player left
	    while (players.size() > 1 && numOfPlayingPlayers > 1) {
		for (Iterator<Player> itr = players.iterator(); itr.hasNext();) {
		    try {
			// Check again that we have enough players to play
			if (players.size() > 1 && numOfPlayingPlayers > 1) {
			    try {
				// Get the Next Player
				Player player = itr.next();
				// Check if the Player is Marked for Deletion
				if (!player.getToDelete()) {
				    if (player.isHuman()) {
					// Inform who is playing-->removed
					//while no input dice is needed from user
					if (!automaticDiceRoll && !player.getToDelete()) {
					    EventArrayResult.addResults(new DiceEvents(GameName, Monopol.getInstance().getEventIDCounter(), TIMEOUT, 6, player.getName(), "Prompt Player to Roll Dice", player.getGame_location()));

					    timer = new Timer("Dice Timeout", true);
					    TimeOutTask = new TimeoutTask(player.getID()); //saves ID in case player won't respond
					    timer.schedule(TimeOutTask, TIMEOUT * 1000); //waits for an answer from user
					    while (waiting) {
						Thread.sleep(200);
					    }
					    waiting = true;
					    if (!player.getToDelete()) {
						gameCubes = cubes.setCubes((DiceEvents) EventArrayResult.getLastEvent());
					    }
					} else if (automaticDiceRoll && !player.getToDelete()) {
					    gameCubes = cubes.rollCubes(player);
					}
				    } // Roll the Cubes and Save the Result
				    else {
					gameCubes = cubes.rollCubes(player);
				    }
				    if (player.getIs_parking() == false && player.getIs_in_prison() == false && !player.getToDelete()) {
					Integer currLocation = player.getGame_location(); // Save the Current location
					// Move the Player to the Next Square in the Game
					player.setGame_location(player.calcGameLocation(gameCubes));
					EventArrayResult.addResults(new MoveEvents(GameName, Monopol.getInstance().getEventIDCounter(), 8, player.getName(), "move ", currLocation, true, player.getGame_location()));
					//Check if Player passed the start square
					// If so, add the required amount to its funds
					player.addFunds(checkGo2Start(currLocation, player.getGame_location(), player.getName()));
					// Move the Player to the Next Square on the Board
					// Check if the New Square is an Asset And Verify that the Player is not Marked for Deletion
					if (squares[player.getGame_location()].isAsset() && !player.getToDelete()) {
					    // This is an Asset - check if Player wants to buy or needs to pay
					    if (squares[player.getGame_location()].isBuyable()) {
						Boolean buyAsset = false;
						// Check if this is a Human Player and if has enuogh money
						if (player.isHuman() && player.getFunds() >= squares[player.getGame_location()].getCost()) {
						    //stores prompt event for buying asset to user
						    EventArrayResult.addResults(new PaymentEvents(GameName, Monopol.getInstance().getEventIDCounter(), TIMEOUT, 12, player.getName(), " Prompt Player to Buy Asset", player.getGame_location(), false, true, null, (squares[player.getGame_location()].getCost()).intValue()));
						    //start timer for prompet
						    timer = new Timer();
						    //if prompet was timedout task will take place
						    TimeOutTask = new TimeoutTask(player.getID()); //saves ID in case player won't respond
						    timer.schedule(TimeOutTask, TIMEOUT * 1000); //waits for an answer from user
						    while (waiting) {
							Thread.sleep(200);
						    }
						    waiting = true;
						    //if prompet response was received
						    if (!player.getToDelete()) {
							buyAsset = ((PaymentEvents) EventArrayResult.getLastEvent()).isPaymentToOrFromTreasury();
						    }
						} else if (player.getFunds() >= squares[player.getGame_location()].getCost()) {
						    buyAsset = true;
						    //buy (int playerID, int eventID, boolean buy);
						}
						// Check if the Player wants to buy this Asset
						if (buyAsset) {
						    try {
							// Buy the Asset
							squares[player.getGame_location()].buy(player);
							// Add the Asset to the Asset List of the Player
							player.buyAsset(squares[player.getGame_location()]);
							if (!player.isHuman()) {
							    EventArrayResult.addResults(new PaymentEvents(
								    GameName, // Set the Game Name
								    Monopol.getInstance().getEventIDCounter(), // Set the Event ID of the New Event
								    14, // Set the Event Type - Asset Bought
								    player.getName(), // Set the Player Name
								    "Asset Bought", // Set the Event Message
								    player.getGame_location(), // Set the Board Square ID
								    true, // Pay to Treasury
								    true, // Pay From the Player
								    null, // No Player Name
								    (squares[player.getGame_location()].getCost()).intValue()));// Set the Amount to Pay
							}
						    } catch (InsufficientFunds trap) {
							// player cant buy no event was added
						    }
						}
					    } // This Asset is Owned by a player can not be bought
					    else {
						// Check if this asset belongs to the player
						if (squares[player.getGame_location()].getOwner() == player) {
						    // Check if this Asset is a City
						    if (squares[player.getGame_location()].isCity()) {
							// This Asset is a City - Cast it
							City c = (City) squares[player.getGame_location()];
							// Check if all the Cities in this City State are owned by this Player
							if (c.getState().isAllAssetGroupMine(player)) {
							    // Check if the Player can buy more houses on this city
							    if (c.getNum_of_houses() < MAX_HOUSES) {
								Boolean addHouse = null;
								// Check that the Player is Human
								if (player.isHuman()) {
								    //stores prompt event for buying House on the City
								    EventArrayResult.addResults(new PaymentEvents(GameName, Monopol.getInstance().getEventIDCounter(), TIMEOUT, 13, player.getName(), "  Prompt Player to Buy House", player.getGame_location(), false, true, null, (squares[player.getGame_location()].getCost()).intValue()));
								    //start timer for prompet
								    timer = new Timer();
								    //if prompet was timedout task will take place
								    TimeOutTask = new TimeoutTask(player.getID()); //saves ID in case player won't respond
								    timer.schedule(TimeOutTask, TIMEOUT * 1000); //waits for an answer from user
								    while (waiting) {
									Thread.sleep(200);
								    }
								    waiting = true;
								    //if prompet response was received
								    if (!player.getToDelete()) {
									addHouse = ((PaymentEvents) EventArrayResult.getLastEvent()).isPaymentToOrFromTreasury();
								    }
								} else // Player is a Computer
								{
								    // Check if the Player have enough money
								    if (player.getFunds() >= c.getHouse_price() + 200) {
									addHouse = true; // Buy a House
								    } else {
									addHouse = false; // Don't buy a House
								    }
								}
								if (addHouse) {
								    // Buy a House
								    try {
									// Buy a House in the City
									c.buyHouse(player);
									if (!player.isHuman()) {
									    EventArrayResult.addResults(new PaymentEvents(
										    GameName, // Set the Game Name
										    Monopol.getInstance().getEventIDCounter(), // Set the Event ID of the New Event
										    15, // Set the Event Type - House Bought
										    player.getName(), // Set the Player Name
										    "House Bought", // Set the Event Message
										    player.getGame_location(), // Set the Board Square ID
										    true, // Pay to Treasury
										    true, // Pay From the Player
										    null, // No Player Name
										    (c.getHouse_price()).intValue()));// Set the Amount to Pay
									}
								    } catch (InsufficientFunds trap) {
									// player cant buy no event was added
								    }
								}
							    } else {
								// This City has the Maximum Number of Houses - No more houses can be built
							    }
							} else {
							    // This City has the Maximum Number of Houses - No more houses can be built
							}
						    } else {
							// The Player doesn't have all the Cities in this state
						    }
						} else if (!player.getToDelete()) {
						    // Save the Current Asset Stay Price
						    Double stay_price = squares[player.getGame_location()].getStay_price();
						    // Check that the Player have enough Funds to pay for it stay
						    if (player.getFunds() >= stay_price) {
							// Update the Players Funds after the payment
							player.addFunds(-stay_price);
							//create event payment event
							EventArrayResult.addResults(new PaymentEvents(GameName, Monopol.getInstance().getEventIDCounter(), 19, player.getName(), " Payment ", player.getGame_location(), false, true, squares[player.getGame_location()].getOwner().getName(), (squares[player.getGame_location()].getStay_price()).intValue()));
							//Adds funds to square owner
							squares[player.getGame_location()].getOwner().addFunds(stay_price);
						    } else // The player does not have enough funds
						    {
							// Check if the Player wants to sell some of his assets to cover for the debt
							try {
							    // Gain the Money needed to stay
							    checkMoneyandAssets(player, stay_price);
							    // Double check that payer has enough money
							    if (player.getFunds() >= stay_price) {
								// Now Player has enough money to pay and stay playing
								player.addFunds(-stay_price);
								//create event payment event
								EventArrayResult.addResults(new PaymentEvents(GameName, Monopol.getInstance().getEventIDCounter(), 19, player.getName(), " Payment ", player.getGame_location(), false, true, squares[player.getGame_location()].getOwner().getName(), (squares[player.getGame_location()].getStay_price()).intValue()));
								//Adds funds to square owner
								squares[player.getGame_location()].getOwner().addFunds(stay_price);
							    } else // Player doesn't have any Money
							    {
								throw new InsufficientFunds();
							    }
							} // If Player has No Assets
							catch (NoAssets na) {
							    //player gets the remaining money of the leaving player
							    squares[player.getGame_location()].getOwner().addFunds(player.getFunds());
							    //create event payment event
							    EventArrayResult.addResults(new PaymentEvents(GameName, Monopol.getInstance().getEventIDCounter(), 19, player.getName(), " Payment ", player.getGame_location(), false, true, squares[player.getGame_location()].getOwner().getName(), (squares[player.getGame_location()].getStay_price()).intValue()));
							    // Take the Money from the Player
							    player.addFunds(-player.getFunds());
							    //delete user from list
							    deletePlayer(player.getID());
							} // If Player Quits
							// If Player Quits
							catch (PlayerQuits pq) {
							    //player gets the remaining money of the leaving player
							    squares[player.getGame_location()].getOwner().addFunds(player.getFunds());
							    //create event payment event
							    EventArrayResult.addResults(new PaymentEvents(GameName, Monopol.getInstance().getEventIDCounter(), 19, player.getName(), " Payment ", player.getGame_location(), false, true, squares[player.getGame_location()].getOwner().getName(), (squares[player.getGame_location()].getStay_price()).intValue()));
							    // Take the Money from the Player
							    player.addFunds(-player.getFunds());
							    //delete user from list
							    deletePlayer(player.getID());
							} //if player made too many auctions
							//if player made too many auctions
							catch (PlayerForcedtoQuit pfq) {
							    //player gets the remaining money of the leaving player
							    squares[player.getGame_location()].getOwner().addFunds(player.getFunds());
							    //create event payment event
							    EventArrayResult.addResults(new PaymentEvents(GameName, Monopol.getInstance().getEventIDCounter(), 19, player.getName(), " Payment ", player.getGame_location(), false, true, squares[player.getGame_location()].getOwner().getName(), (squares[player.getGame_location()].getStay_price()).intValue()));
							    // Take the Money from the Player
							    player.addFunds(-player.getFunds());
							    //delete user from list
							    deletePlayer(player.getID());
							} catch (InsufficientFunds e) {
							    //player gets the remaining money of the leaving player
							    squares[player.getGame_location()].getOwner().addFunds(player.getFunds());
							    //create event payment event
							    EventArrayResult.addResults(new PaymentEvents(GameName, Monopol.getInstance().getEventIDCounter(), 19, player.getName(), " Payment ", player.getGame_location(), false, true, squares[player.getGame_location()].getOwner().getName(), (squares[player.getGame_location()].getStay_price()).intValue()));
							    // Take the Money from the Player
							    player.addFunds(-player.getFunds());
							    //delete user from list
							    deletePlayer(player.getID());
							}
						    }
						}
					    }
					} else if (!player.getToDelete()) {
					    try {
						// Check if this is a Parking Square
						if (squares[player.getGame_location()].getName().equals("Parking")) {
						    // Set the Player state as Parking
						    player.setIs_parking(true);
						} // Check if this is the Go to Prison Square
						else if (squares[player.getGame_location()].getName().equals("Go to Prison")) {
						    player.setGame_location(fixedSquares.GO2PRISON_SQUARE.get()); // Set location as prison square
						    // Set the Player state as in Prison
						    player.setIs_in_prison(true);
						    // Inform the Other Players

						    EventArrayResult.addResults(new GameEvents(GameName, Monopol.getInstance().getEventIDCounter(), 11, player.getName(), " Go to Jail ", currLocation));
						    EventArrayResult.addResults(new MoveEvents(GameName, Monopol.getInstance().getEventIDCounter(), 8, player.getName(), " Move", currLocation, true, fixedSquares.PRISON_SQUARE.get()));
						    player.setGame_location(fixedSquares.PRISON_SQUARE.get());
						} // Check if this is a Warning Card Square
						else if (squares[player.getGame_location()].getName().equals("Warning")) {
						    playWarningCard(squares[player.getGame_location()].getName(), player); // Handle warning card
						} else if (squares[player.getGame_location()].getName().equals("Surprise")) {
						    playSurpriseCard(squares[player.getGame_location()].getName(), player); // Handle surprise card
						}
					    } catch (WrongCardType w) {
						// Handle surprise card
					    }
					}
				    } else if (!player.getToDelete()) {
					// Check if the Player is in Prison
					if (player.getIs_in_prison()) {
					    // Check if the Players Cubes are Double
					    if (cubes.isDouble) {
						// The player scored a Double in the Game Cubes - Release from prison
						player.setIs_in_prison(false);
						//todo						// Inform the Player that it is released from prison
					    } else {
						// The Player does not have a Get out of Prison Card
						// Check if the Player has the Get out of Prison Card and use it
						if (player.getRelease_from_prison_card()) {
						    try {
							// Release the Player from Prison
							player.setIs_in_prison(false);
							// Return the Get out of Prison Card to the Deck
							player.setGetoutOfPrisonCard(false);
							// Return the Saved Card back to the Deck
							surprise_cards.add(saved_card);
							//notify players
							EventArrayResult.addResults(new GameEvents(GameName, Monopol.getInstance().getEventIDCounter(), 20, player.getName(), "  Player used Get out of jail card ", player.getGame_location()));
						    } catch (Error e) {
							// This Should never happen
							throw new RuntimeException("Something Terrible just Happened...\n" + e.toString());
						    }
						} else {
						    // The Player does not have a Get out of Prison Card
						}
					    }
                                            // Notify on No Move
                                            EventArrayResult.addResults(new MoveEvents(
                                                    GameName, // Set the Game Name
                                                    Monopol.getInstance().getEventIDCounter(), // Set the Event ID
                                                    8, // Set the Event Type - Move Event
                                                    player.getName(),
                                                    "The Player is still in Prison", // Set the Event Message
                                                    player.getGame_location(), // Set the Current Game Board Square ID
                                                    false, // Set The Event with NO Movment
                                                    player.getGame_location()) // Set the Current Game Board Square ID)
                                                 );
					} // Check if the Player is in Parking
					else if (player.getIs_parking() && !player.getToDelete()) {
					    // The player is in Parking
					    // Change the Player Status so he would be able to play next turn
					    player.setIs_parking(false);
                                            // Notify on No Move
                                            EventArrayResult.addResults(new MoveEvents(
                                                    GameName, // Set the Game Name
                                                    Monopol.getInstance().getEventIDCounter(), // Set the Event ID
                                                    8, // Set the Event Type - Move Event
                                                    player.getName(),
                                                    "The Player finished his parking", // Set the Event Message
                                                    player.getGame_location(), // Set the Current Game Board Square ID
                                                    false, // Set The Event with NO Movment
                                                    player.getGame_location()) // Set the Current Game Board Square ID)
                                                 );
					}
				    } // End Check Prison or Parking
				    else {
					//player was deleted by java application
					// Set the User for deletion
					//deletePlayer(player);
				    }
				} else // The User is Marked for Deletion
				{
				    // Remove the Player from the Array
				    //itr.remove();
				}
				// Update the Game GUI of the Changes
				// Update the Game GUI of the Changes
			    } catch (DeletePlayer dp) {
				// Set the User for deletion
				dp.deletedPlayer.setToDelete(true);
			    }
			} // End Checking for Players
			else {
			    // Get the Next Player - finish the round (the For Each)
			    itr.next();
			}
			//adding thread in order to lower delay between client and server
			wait(10000);

		    } // End ForEach Loop
		    catch (InterruptedException ex) {
			System.out.println("problem with putting main thread to sleep");
		    }
		} // End ForEach Loop
	    } // End While Loop    }
	} catch (MonopolErrors ex) {
	    Logger.getLogger(Monopol.class.getName()).log(Level.SEVERE, null, ex);
	}

//	// Clean up the Players List
//	for (Iterator<Player> itr = players.iterator(); itr.hasNext();) {
//	    // Check if this Player is Marked for Deletion
//	    if (itr.next().getToDelete()) {
//		// Remove the Player from the List
//		itr.remove();
//	    }
//	}

	// No more Players in the Game but 1

	// The Last Player is the Winner - It will be the Only player left in the Array List
	if (numOfPlayingPlayers == 1) {
	    // Print Out the Winning Player
	    for (Player player : players) {
		if (!player.getToDelete()) {
		    EventArrayResult.addResults(new GameEvents(GameName, Monopol.getInstance().getEventIDCounter(), 3, player.getName(), "    Game Winner  ", player.getGame_location()));
		}
	    }

	    
	} else {
	    // Write an Error Message "Error!\nThere is more than 1 Player!\n"
	    System.out.println("Error!\nThere is more than 1 Player!\nPlayer Array Size:" + players.size());
	}
// Print Out game over
	    EventArrayResult.addResults(new GameEvents(GameName, Monopol.getInstance().getEventIDCounter(), 2, null, "   Game Over  ", 0));
	//"Game Over!"
    }

    /**
     * This Function Plays a Warning Card for the Player
     * @param Square_Type The Type of the Square being Checked
     * @param player The Player that is on the Square
     * @throws WrongCardType
     * @throws DeletePlayer
     */
    public void playWarningCard(String Square_Type, Player player) throws WrongCardType, DeletePlayer {
	// Define a Boolean to check whether the Turn is over or not
	Boolean isTurnOver = false;
	// Verify the Square Type
	if (Square_Type.equals("Warning")) {
	    while (isTurnOver == false) // Loop until player arrives at final square (Then the turn will be over)
	    {
		Card selected_card = warning_cards.remove(0); // Player takes card from the deck
		EventArrayResult.addResults(new GameEvents(GameName, Monopol.getInstance().getEventIDCounter(), 17, player.getName(), selected_card.getDescription(), player.getGame_location()));
		// Check if the Card is A Move Card or a Money Card
		if (selected_card instanceof Move_card) {
		    Move_card move_card = (Move_card) selected_card;
		    // Player got a 'Go to Prison' Card
		    if (move_card.getSpecific_location() == eGoTo.PRISON) {
                        //notify
			EventArrayResult.addResults(new GameEvents(GameName, Monopol.getInstance().getEventIDCounter(), 11, player.getName(), " Go to Jail", player.getGame_location()));
			EventArrayResult.addResults(new MoveEvents(GameName, Monopol.getInstance().getEventIDCounter(), 8, player.getName(), "  Move", player.getGame_location(), true, fixedSquares.PRISON_SQUARE.get()));
			// Put the Player in Prison
			// Set the Player Location to Prison
			player.setGame_location(fixedSquares.PRISON_SQUARE.get()); // Set location as prison square
			// Update the Player that he is in Prison
			player.setIs_in_prison(true);
			// Return the Card back to the Deck
			warning_cards.add(selected_card);
			// Exit the While Loop - Turn is Over
			isTurnOver = true;
			
		    } // Player got the 'Go to next Warning Card' Card
		    else if (move_card.getSpecific_location() == eGoTo.NEXT_WARNING) {
			// Save the Location of the Next Square
			Integer newLocation = player.getGame_location() + 1;
			Integer prevLocation = player.getGame_location();
			// Find the Next Warning Card Square
			while (!squares[newLocation].getName().equals("Warning")) {
			    newLocation = (newLocation + 1) % 36;
			    // Move the Player
			    // Put the Player in the Next Warning Square
			    player.setGame_location(newLocation);
			}
			//notify
			EventArrayResult.addResults(new MoveEvents(GameName, Monopol.getInstance().getEventIDCounter(), 8, player.getName(), " Go to next warning square", prevLocation, true, newLocation));


			// Player Returns card and will take another card next loop
			warning_cards.add(selected_card);
		    }
		} // Player got a Fine (a Money Card)
		else {
		    // This is a Money Card
		    Money_card card = (Money_card) selected_card;


		    // Check if the Money is Shared between the Players
		    if (card.getCashier() == false) {

			// Check if the Player have enough money to pay all the players
			if (player.getFunds() >= (card.getAmount() * (numOfPlayingPlayers - 1))) {
			    // Loop all the Players
			    for (Player oPlayer : players) // Check that this is not the Player that is Playing
			    {
				// Verify that the User is still active
				if (!oPlayer.getToDelete()) {
				    // Verify that this is not the Player who needs to Pay
				    if (oPlayer != player) {
					// Pay the Other Players the Amount of money Needed
					oPlayer.addFunds(card.getAmount());
					// Inform The Other Users
					EventArrayResult.addResults(new PaymentEvents(
						GameName, // Set the Game Name
						Monopol.getInstance().getEventIDCounter(), // Set the Event ID
						19, // Set the Event Type - Payment Event
						player.getName(), // Set the Player Name
						player.getName() + "Paid " + oPlayer.getName() + ", " + card.getAmount().toString() + " Shekels.", // Set the Event Message
						player.getGame_location(), // Set the Gameboard Square ID
						false, // Set the Pay to Or From Treasury (Payment is From Player)
						true, // Set Pay To Other Player
						oPlayer.getName(), // Set the Player To Pay To
						card.getAmount().intValue()) // Set the Paytment Amount
						);
				    }
				}
			    }
			    // Remove the Amount of money payed to the other Players from this player
			    player.addFunds(-(card.getAmount() * (numOfPlayingPlayers - 1)));
			    // Inform The Other Users
			} else {
			    try {
				// Player does not have enough money to pay all the players
				checkMoneyandAssets(player, (card.getAmount() * (numOfPlayingPlayers - 1)));
				// Check if the Player have enough money to pay all the players
				if (player.getFunds() >= (card.getAmount() * (numOfPlayingPlayers - 1))) {
				    // Now the Player have enough Money to pay the debt
				    // Loop all the Players
				    for (Player oPlayer : players) // Check that this is not the Player that is Playing
				    {
					// Verify that the User is still active
					if (!oPlayer.getToDelete()) {
					    // Verify that this is not the Player who needs to Pay, and that the Payong Player has Money
					    if (oPlayer != player && player.getFunds() > 0) {
						// Pay the Other Players the Amount of money Needed
						oPlayer.addFunds(card.getAmount());
						// Inform The Other Users
						EventArrayResult.addResults(new PaymentEvents(
							GameName, // Set the Game Name
							Monopol.getInstance().getEventIDCounter(), // Set the Event ID
							19, // Set the Event Type - Payment Event
							player.getName(), // Set the Player Name
							player.getName() + "Paid " + oPlayer.getName() + ", " + card.getAmount().toString() + " Shekels (It Sold Some Assets).", // Set the Event Message
							player.getGame_location(), // Set the Gameboard Square ID
							false, // Set the Pay to Or From Treasury (Payment is From Player)
							true, // Set Pay To Other Player
							oPlayer.getName(), // Set the Player To Pay To
							card.getAmount().intValue()) // Set the Paytment Amount
							);
					    }
					}
				    }
				    // Remove the Amount of money payed to the other Players from this player
				    player.addFunds(-(card.getAmount() * (numOfPlayingPlayers - 1)));
				    // Inform The Other Users
				} else {

				    // Get the Amount of Divided Money
				    Double dividedMoney = (player.getFunds() / (numOfPlayingPlayers - 1));
				    for (Player oPlayer : players) // Check that this is not the Player that is Playing
				    {
					// Verify that the User is still active
					if (!oPlayer.getToDelete()) {
					    // Verify that this is not the Player who needs to Pay, and that the Payong Player has Money
					    if (oPlayer != player && player.getFunds() > 0) {
						// Pay the rest of the Money of this player to the other players
						oPlayer.addFunds(dividedMoney);
						// Take Money from Player
						player.addFunds(-dividedMoney);
						// Inform The Other Users
						EventArrayResult.addResults(new PaymentEvents(
							GameName, // Set the Game Name
							Monopol.getInstance().getEventIDCounter(), // Set the Event ID
							19, // Set the Event Type - Payment Event
							player.getName(), // Set the Player Name
							player.getName() + " Paid " + oPlayer.getName() + ", " + dividedMoney.toString() + " Shekels (It Doesnt Have enough Money).", // Set the Event Message
							player.getGame_location(), // Set the Gameboard Square ID
							false, // Set the Pay to Or From Treasury (Payment is From Player)
							true, // Set Pay To Other Player
							oPlayer.getName(), // Set the Player To Pay To
							(dividedMoney).intValue()) // Set the Divided Paytment Amount
							);
					    }
					}
				    }
				    // Delete the Player - Has No More funds
				    if (deletePlayer(player)) {
					// Delete the Player
					EventArrayResult.addResults(new GameEvents(
						GameName, // Set the Game Name
						Monopol.getInstance().getEventIDCounter(), // Set the Event ID
						5, // Set the Event Type - Plaer Lost
						player.getName(), // Set the Player Name - The Player who Lost
						" Player Lost", // Set the Event Message
						player.getGame_location()) // Set the Player Location
						);
					throw new DeletePlayer(player);
				    }
				}
			    } // If Player has No Assets
			    catch (NoAssets na) {
				// Check that the Player has money to divide
				if (player.getFunds() > 0) {
				    // Get the Amount of Divided Money
				    Double dividedMoney = (player.getFunds() / (numOfPlayingPlayers - 1));
				    for (Player oPlayer : players) // Check that this is not the Player that is Playing
				    {
					// Verify that the User is still active
					if (!oPlayer.getToDelete()) {
					    // Verify that this is not the Player who needs to Pay, and that the Payong Player has Money
					    if (oPlayer != player && player.getFunds() > 0) {
						// Pay the rest of the Money of this player to the other players
						oPlayer.addFunds(dividedMoney);
						// Take Money from Player
						player.addFunds(-dividedMoney);
						// Inform The Other Users
						EventArrayResult.addResults(new PaymentEvents(
							GameName, // Set the Game Name
							Monopol.getInstance().getEventIDCounter(), // Set the Event ID
							19, // Set the Event Type - Payment Event
							player.getName(), // Set the Player Name
							player.getName() + " Paid " + oPlayer.getName() + ", " + dividedMoney.toString() + " Shekels (It Has No  More Assets).", // Set the Event Message
							player.getGame_location(), // Set the Gameboard Square ID
							false, // Set the Pay to Or From Treasury (Payment is From Player)
							true, // Set Pay From Other Player
							oPlayer.getName(), // Set the Player To Pay To
							(dividedMoney).intValue()) // Set the Divided Paytment Amount
							);
					    }
					}
				    }
				    // Delete the Player - Has No More funds
				    if (deletePlayer(player)) {
					// Delete the Player
					EventArrayResult.addResults(new GameEvents(
						GameName, // Set the Game Name
						Monopol.getInstance().getEventIDCounter(), // Set the Event ID
						5, // Set the Event Type - Plaer Lost
						player.getName(), // Set the Player Name - The Player who Lost
						" Player Lost", // Set the Event Message
						player.getGame_location()) // Set the Player Location
						);
					throw new DeletePlayer(player);
				    }
				}
			    } // If Player Quits
			    catch (PlayerQuits pq) {
				// Check that the Player has money to divide
				if (player.getFunds() > 0) {
				    // Get the Amount of Divided Money
				    Double dividedMoney = (player.getFunds() / (numOfPlayingPlayers - 1));
				    for (Player oPlayer : players) // Check that this is not the Player that is Playing
				    {
					// Verify that the User is still active
					if (!oPlayer.getToDelete()) {
					    // Verify that this is not the Player who needs to Pay, and that the Payong Player has Money
					    if (oPlayer != player && player.getFunds() > 0) {
						// Pay the rest of the Money of this player to the other players
						oPlayer.addFunds(dividedMoney);
						// Take Money from Player
						player.addFunds(-dividedMoney);
						// Inform The Other Users
						EventArrayResult.addResults(new PaymentEvents(
							GameName, // Set the Game Name
							Monopol.getInstance().getEventIDCounter(), // Set the Event ID
							19, // Set the Event Type - Payment Event
							player.getName(), // Set the Player Name
							player.getName() + " Paid " + oPlayer.getName() + ", " + dividedMoney.toString() + " Shekels (Player Quited the Game).", // Set the Event Message
							player.getGame_location(), // Set the Gameboard Square ID
							false, // Set the Pay to Or From Treasury (Payment is From Player)
							true, // Set Pay From Other Player
							oPlayer.getName(), // Set the Player To Pay To
							(dividedMoney).intValue()) // Set the Divided Paytment Amount
							);
					    }
					}
				    }
				    // Delete the Player - Has No More funds
				    if (deletePlayer(player)) {
					// Delete the Player
					EventArrayResult.addResults(new GameEvents(
						GameName, // Set the Game Name
						Monopol.getInstance().getEventIDCounter(), // Set the Event ID
						5, // Set the Event Type - Plaer Lost
						player.getName(), // Set the Player Name - The Player who Lost
						" Player Lost", // Set the Event Message
						player.getGame_location()) // Set the Player Location
						);
					throw new DeletePlayer(player);
				    }
				}
			    } //if player made too many auctions
			    catch (PlayerForcedtoQuit pfq) {
				// Check that the Player has money to divide
				if (player.getFunds() > 0) {
				    // Get the Amount of Divided Money
				    Double dividedMoney = (player.getFunds() / (numOfPlayingPlayers - 1));
				    // Loop the Players and Pay them the Money
				    for (Player oPlayer : players) // Check that this is not the Player that is Playing
				    {
					// Verify that the User is still active
					if (!oPlayer.getToDelete()) {
					    // Verify that this is not the Player who needs to Pay
					    if (oPlayer != player && player.getFunds() > 0) {
						// Pay the rest of the Money of this player to the other players
						oPlayer.addFunds(dividedMoney);
						// Take Money from Player
						player.addFunds(-dividedMoney);
						// Inform The Other Users
						EventArrayResult.addResults(new PaymentEvents(
							GameName, // Set the Game Name
							Monopol.getInstance().getEventIDCounter(), // Set the Event ID
							19, // Set the Event Type - Payment Event
							player.getName(), // Set the Player Name
							player.getName() + " Paid " + oPlayer.getName() + ", " + dividedMoney.toString() + " Shekels (Player was Forced to Quit the Game).", // Set the Event Message
							player.getGame_location(), // Set the Gameboard Square ID
							false, // Set the Pay to Or From Treasury (Payment is From Player)
							true, // Set Pay From Other Player
							oPlayer.getName(), // Set the Player To Pay To
							(dividedMoney).intValue()) // Set the Divided Paytment Amount
							);
					    }
					}
				    }
				    // Delete the Player - Has No More funds
				    if (deletePlayer(player)) {
					// Delete the Player
					EventArrayResult.addResults(new GameEvents(
						GameName, // Set the Game Name
						Monopol.getInstance().getEventIDCounter(), // Set the Event ID
						5, // Set the Event Type - Plaer Lost
						player.getName(), // Set the Player Name - The Player who Lost
						" Player Lost", // Set the Event Message
						player.getGame_location()) // Set the Player Location
						);
					throw new DeletePlayer(player);
				    }
				}
			    }
			}
		    } // End payment to Players
		    else {
			// The Money is Going to the Cashier
			if (player.getFunds() > card.getAmount()) {
			    //Pay the Cash and Update the Players Funds
			    player.addFunds(-card.getAmount());
			    // Add the Money to the Cashier
			    cashier += card.getAmount();
			    // Update the Cash in the Game Cashier
			    // Inform The Other Users
			    EventArrayResult.addResults(new PaymentEvents(
				    GameName, // Set the Game Name
				    Monopol.getInstance().getEventIDCounter(), // Set the Event ID
				    19, // Set the Event Type - Payment Event
				    player.getName(), // Set the Player Name
				    player.getName() + " Paid The Treasury " + card.getAmount().toString() + " Shekels.", // Set the Event Message
				    player.getGame_location(), // Set the Gameboard Square ID
				    true, // Set the Pay to Or From Treasury (Payment is To Treasury)
				    true, // Set Pay From The Player
				    null, // Set the Player To Pay To - No one
				    (card.getAmount()).intValue())  // Set the Paytment Amount
				);
			} else {
			    // Player does not have enough money to pay
			    try {
				checkMoneyandAssets(player, card.getAmount());
				// Double Check that Payer has enough money
				if (player.getFunds() >= card.getAmount()) {
				    // Now the Player have enough Money to pay the debt
				    player.addFunds(-card.getAmount());
				    // Add the Money to the Cashier
				    cashier += card.getAmount();
				    // Update the Cash in the Game Cashier
				    // Inform The Other Users
				    EventArrayResult.addResults(new PaymentEvents(
					    GameName, // Set the Game Name
					    Monopol.getInstance().getEventIDCounter(), // Set the Event ID
					    19, // Set the Event Type - Payment Event
					    player.getName(), // Set the Player Name
					    player.getName() + " Paid The Treasury " + card.getAmount().toString() + " Shekels (it Sold some Assets).", // Set the Event Message
					    player.getGame_location(), // Set the Gameboard Square ID
					    true, // Set the Pay to Or From Treasury (Payment is To Treasury)
					    true, // Set Pay From The Player
					    null, // Set the Player To Pay To - No one
					    (card.getAmount()).intValue()) // Set the Paytment Amount
					    );
				} else // Player doesn't have enough money
				{
				    throw new InsufficientFunds();
				}
			    } // If Player has No Assets
			    catch (NoAssets na) {
				if (deletePlayer(player)) {
				    // Delete the Player
				    EventArrayResult.addResults(new GameEvents(
					    GameName, // Set the Game Name
					    Monopol.getInstance().getEventIDCounter(), // Set the Event ID
					    5, // Set the Event Type - Plaer Lost
					    player.getName(), // Set the Player Name - The Player who Lost
					    " Player Lost", // Set the Event Message
					    player.getGame_location()) // Set the Player Location
					    );
				    throw new DeletePlayer(player);
				}
			    } // If Player Quits
			    catch (PlayerQuits pq) {
				if (deletePlayer(player)) {
				    // Delete the Player
				    EventArrayResult.addResults(new GameEvents(
					    GameName, // Set the Game Name
					    Monopol.getInstance().getEventIDCounter(), // Set the Event ID
					    5, // Set the Event Type - Plaer Lost
					    player.getName(), // Set the Player Name - The Player who Lost
					    " Player Lost", // Set the Event Message
					    player.getGame_location()) // Set the Player Location
					    );
				    throw new DeletePlayer(player);
				}
			    } // If player made too many auctions
			    catch (PlayerForcedtoQuit pfq) {
				if (deletePlayer(player)) {
				    // Delete the Player
				    EventArrayResult.addResults(new GameEvents(
					    GameName, // Set the Game Name
					    Monopol.getInstance().getEventIDCounter(), // Set the Event ID
					    5, // Set the Event Type - Plaer Lost
					    player.getName(), // Set the Player Name - The Player who Lost
					    " Player Lost", // Set the Event Message
					    player.getGame_location()) // Set the Player Location
					    );
				    throw new DeletePlayer(player);
				}
			    } catch (InsufficientFunds e) {// Delete the Player
				if (deletePlayer(player)) {
				    // Delete the Player
				    EventArrayResult.addResults(new GameEvents(
					    GameName, // Set the Game Name
					    Monopol.getInstance().getEventIDCounter(), // Set the Event ID
					    5, // Set the Event Type - Plaer Lost
					    player.getName(), // Set the Player Name - The Player who Lost
					    " Player Lost", // Set the Event Message
					    player.getGame_location()) // Set the Player Location
					    );
				    throw new DeletePlayer(player);
				}
			    }
			}
		    } // End Payment to Cashier
		    // Player returns the card
		    warning_cards.add(selected_card);
		    // Exit the While Loop - Turn is Over
		    isTurnOver = true;
		} // End Square Checking
	    } // End While
	} else // The Card Received is Wrong
	{
	    throw new WrongCardType("Error! Wrong Card Type!\nExpected Warning Card and received a " + Square_Type + " Card.\n");
	}
    }

    /**
     * This Function Plays a Surprise card for the Player
     * @param Square_Type The Type of the Square being Checked
     * @param player The Player that is on the Square
     * @throws WrongCardType
     * @throws DeletePlayer
     */
    public void playSurpriseCard(String Square_Type, Player player) throws WrongCardType, DeletePlayer {
	// Define a Boolean to check whether the Turn is over or not
	Boolean isTurnOver = false;
	// Verify the Square Type
	if (Square_Type.equals("Surprise")) {
	    // Loop until the Turn is Over
	    while (isTurnOver == false) {
		// Pick up the First card from the Deck
		Card selected_card = surprise_cards.remove(0);
		EventArrayResult.addResults(new GameEvents(GameName, Monopol.getInstance().getEventIDCounter(), 16, player.getName(), selected_card.getDescription(), player.getGame_location()));
		if (selected_card instanceof Move_card) {
		    Move_card move_card = (Move_card) selected_card;
		    // Check if Player got the 'Go to Start' Card
		    if (move_card.getSpecific_location() == eGoTo.START) {
			// Adds 400 shekels to funds
			EventArrayResult.addResults(new MoveEvents(GameName, Monopol.getInstance().getEventIDCounter(), 8, player.getName(), "Go to  Game Start", player.getGame_location(), true, fixedSquares.START_SQUARE.get()));
			player.addFunds(checkGo2Start(player.getGame_location(), fixedSquares.START_SQUARE.get(), player.getName()));
			// Move the Player
			// Set Players location to the start square
			player.setGame_location(fixedSquares.START_SQUARE.get());
			// Return the Card to the Deck
			surprise_cards.add(selected_card);
			// Exit the While Loop - Turn is Over
			isTurnOver = true;
		    } // Check if the Player get the 'Go to Next Surprise' Card
		    else if (move_card.getSpecific_location() == eGoTo.NEXT_SURPRISE) {
			// Save the Next Square
			Integer newLocation = player.getGame_location() + 1;
			Integer prevLocation = player.getGame_location();
			// Find the Next Surprise Square
			while (!squares[newLocation].getName().equals("Surprise")) {
			    // Increment the Square Location
			    newLocation = (newLocation + 1) % 36;
			    // Player will pass the Start Square in the next Square - pay it Once.
			    if (newLocation == 0) {
				// Check if the Player passed the Start Square and add money if Needed
				player.addFunds(checkGo2Start(player.getGame_location(), newLocation + 1, player.getName()));
			    }
			    // Move the Player
			    // Sets the players new location
			    player.setGame_location(newLocation);
			}
			//notify
			EventArrayResult.addResults(new MoveEvents(GameName, Monopol.getInstance().getEventIDCounter(), 8, player.getName(), " Go to next surprise square", prevLocation, true, newLocation));

			// Returns card and will take another card next loop
			surprise_cards.add(selected_card);

		    } // Player got a Present Card (Money Card)
		} else if (selected_card instanceof Money_card) {
		    // This is a Money Card
		    Money_card card = (Money_card) selected_card;
		    // Check if the Money needs to be paid from the other Players or not
		    if (card.getCashier() == false) {
			// Loop all the Players
			for (Player oPlayer : players) {
			    if(!oPlayer.getToDelete()){
			    // Check that this is not the Player that is Playing
			    if (oPlayer != player) {
				if (oPlayer.getFunds() >= card.getAmount()) {
				    // Reduce from the Other Players the Amount of money Needed
				    oPlayer.addFunds(-(card.getAmount()));
				    // Add the Player the Amount from other player
				    player.addFunds(card.getAmount());
				    // Inform The Other Users
				    EventArrayResult.addResults(new PaymentEvents(
					    GameName, // Set the Game Name
					    Monopol.getInstance().getEventIDCounter(),  // Set the Event ID
					    19, // Set the Event Type - Payment
					    oPlayer.getName(),  // Set the Player Name
					    player.getName() + " Got " + card.getAmount().toString() + " Shekels from " + oPlayer.getName() + ".",  // Set the Event Message
					    player.getGame_location(),  // Set the Current Square ID
					    false,  // Set Payment is Done TO a Player
					    false,  // Set Payment FROM Other Players
					    player.getName(),
					    (card.getAmount()).intValue())
					    );

				} else {
				    try {
					// Player does not have enough money to pay all the players
					checkMoneyandAssets(oPlayer, card.getAmount());
					// Double Check that player has enough money
					if (oPlayer.getFunds() >= card.getAmount()) {
					    // Now the Player have enough Money to pay the debt
					    oPlayer.addFunds(-card.getAmount());
					    // Add the Player the Amount from other player
					    player.addFunds(card.getAmount());
					    // Inform The Other Users
					    EventArrayResult.addResults(new PaymentEvents(
					    GameName, // Set the Game Name
					    Monopol.getInstance().getEventIDCounter(),  // Set the Event ID
					    19, // Set the Event Type - Payment
					    oPlayer.getName(),  // Set the Player Name
					    player.getName() + " Got " + card.getAmount().toString() + " Shekels from " + oPlayer.getName() + " (It Sold Some Assets).",  // Set the Event Message
					    player.getGame_location(),  // Set the Current Square ID
					    false,  // Set Payment is Done TO a Player
					    false,  // Set Payment FROM Other Players
					    player.getName(),
					    (card.getAmount()).intValue())
					    );

					} else // Player has no Money
					if (!oPlayer.getToDelete()) // Check that the Player is not Marked for deletion
					{
					    throw new InsufficientFunds();
					}
				    } // If Player has No Assets
				    catch (NoAssets na) {
					//player gets the remaining money of the leaving player
					player.addFunds(oPlayer.getFunds());
					// Inform Other Players
					EventArrayResult.addResults(new PaymentEvents(
					    GameName, // Set the Game Name
					    Monopol.getInstance().getEventIDCounter(),  // Set the Event ID
					    19, // Set the Event Type - Payment
					    oPlayer.getName(),  // Set the Player Name
					    player.getName() + " Got " + oPlayer.getFunds().toString() + " Shekels from " + oPlayer.getName() + " (It has no Assets).",  // Set the Event Message
					    player.getGame_location(),  // Set the Current Square ID
					    false,  // Set Payment is Done TO a Player
					    false,  // Set Payment FROM Other Players
					    player.getName(),
					    (oPlayer.getFunds()).intValue())
					    );
					// Take the Money from the Player
					oPlayer.addFunds(-oPlayer.getFunds());
					// Delete the Player
					if (deletePlayer(oPlayer)) {
					     // Delete the Player
					EventArrayResult.addResults(new GameEvents(
						GameName, // Set the Game Name
						Monopol.getInstance().getEventIDCounter(),  // Set the Event ID
						5, // Set the Event Type - Plaer Lost
						player.getName(),  // Set the Player Name - The Player who Lost
						" Player Lost",  // Set the Event Message
						player.getGame_location()) // Set the Player Location
					);
					    throw new DeletePlayer(oPlayer);
					}
				    } // If Player Quits
				    catch (PlayerQuits pq) {
					//player gets the remaining money of the leaving player
					player.addFunds(oPlayer.getFunds());
					// Inform Other Players
					EventArrayResult.addResults(new PaymentEvents(
					    GameName, // Set the Game Name
					    Monopol.getInstance().getEventIDCounter(),  // Set the Event ID
					    19, // Set the Event Type - Payment
					    oPlayer.getName(),  // Set the Player Name
					    player.getName() + " Got " + oPlayer.getFunds().toString() + " Shekels from " + oPlayer.getName() + " (Player Quited the Game).",  // Set the Event Message
					    player.getGame_location(),  // Set the Current Square ID
					    false,  // Set Payment is Done TO a Player
					    false,  // Set Payment FROM Other Players
					   player.getName(),
					    (oPlayer.getFunds()).intValue())
					    );
					// Take the Money from the Player
					oPlayer.addFunds(-oPlayer.getFunds());
					// Delete the Player
					if (deletePlayer(oPlayer)) {
					     // Delete the Player
					EventArrayResult.addResults(new GameEvents(
						GameName, // Set the Game Name
						Monopol.getInstance().getEventIDCounter(),  // Set the Event ID
						5, // Set the Event Type - Plaer Lost
						player.getName(),  // Set the Player Name - The Player who Lost
						" Player Lost",  // Set the Event Message
						player.getGame_location()) // Set the Player Location
					);
					    throw new DeletePlayer(oPlayer);
					}
				    } //if player made too many auctions
				    catch (PlayerForcedtoQuit pfq) {
					//player gets the remaining money of the leaving player
					player.addFunds(oPlayer.getFunds());
					// Inform Other Players
					EventArrayResult.addResults(new PaymentEvents(
					    GameName, // Set the Game Name
					    Monopol.getInstance().getEventIDCounter(),  // Set the Event ID
					    19, // Set the Event Type - Payment
					    oPlayer.getName(),  // Set the Player Name
					    player.getName() + " Got " + oPlayer.getFunds().toString() + " Shekels from " + oPlayer.getName() + " (Player was Forced to Quit).",  // Set the Event Message
					    player.getGame_location(),  // Set the Current Square ID
					    false,  // Set Payment is Done TO a Player
					    false,  // Set Payment FROM Other Players
					    player.getName(),
					    (oPlayer.getFunds()).intValue())
					    );
					// Take the Money from the Player
					oPlayer.addFunds(-oPlayer.getFunds());
					// Delete the Player
					if (deletePlayer(oPlayer)) {
					     // Delete the Player
					EventArrayResult.addResults(new GameEvents(
						GameName, // Set the Game Name
						Monopol.getInstance().getEventIDCounter(),  // Set the Event ID
						5, // Set the Event Type - Plaer Lost
						player.getName(),  // Set the Player Name - The Player who Lost
						" Player Lost",  // Set the Event Message
						player.getGame_location()) // Set the Player Location
					);
					    throw new DeletePlayer(oPlayer);
					}
				    } catch (InsufficientFunds e) {
					//player gets the remaining money of the leaving player
					player.addFunds(oPlayer.getFunds());
					// Inform Other Players
					EventArrayResult.addResults(new PaymentEvents(
					    GameName, // Set the Game Name
					    Monopol.getInstance().getEventIDCounter(),  // Set the Event ID
					    19, // Set the Event Type - Payment
					    oPlayer.getName(),  // Set the Player Name
					    player.getName() + " Got " + oPlayer.getFunds().toString() + " Shekels from " + oPlayer.getName() + " (It has no Money).",  // Set the Event Message
					    player.getGame_location(),  // Set the Current Square ID
					    false,  // Set Payment is Done TO a Player
					    false,  // Set Payment FROM Other Players
					    player.getName(),
					    (oPlayer.getFunds()).intValue())
					    );
					// Take the Money from the Player
					oPlayer.addFunds(-oPlayer.getFunds());
					// Delete the Player
					if (deletePlayer(oPlayer)) {
					     // Delete the Player
					EventArrayResult.addResults(new GameEvents(
						GameName, // Set the Game Name
						Monopol.getInstance().getEventIDCounter(),  // Set the Event ID
						5, // Set the Event Type - Player Lost
						player.getName(),  // Set the Player Name - The Player who Lost
						" Player Lost",  // Set the Event Message
						player.getGame_location()) // Set the Player Location
					);
					    throw new DeletePlayer(oPlayer);
					}
				    }
				}
			    }
			}
			}
		    } else {
			// Money come from the Cashier
			player.addFunds(card.getAmount());
			// Take the Money from the Cashier
			cashier -= card.getAmount();
			// Update the Cash in the Game Cashier
			// Inform The Other Users
			EventArrayResult.addResults(new PaymentEvents(
				GameName, // Set the Game Name
				Monopol.getInstance().getEventIDCounter(),  // Set the Event ID
				19,  // Set the Event Type - Payment
				player.getName(),  // Set the Player Name
				player.getName() + " Got " + card.getAmount().toString() + " Shekels from chasier.",  // Set the Event Message
				player.getGame_location(),  // Set the Current Square ID
				true,  // Set the Payment FROM the Treasury
				false,  // Set the Payment TO the Player
				player.getName(), // Set the Player Name
				(card.getAmount()).intValue()) // Set the Amount
				);

		    }
		    // Exit the While Loop - Turn is Over
		    isTurnOver = true;
		    // Return the card to the Deck
		    surprise_cards.add(selected_card);
		} // End of Present
		//  The Player got the 'Get out of Prison' Card
		else {
		    // Save the Card
		    saved_card = selected_card;
		    // Inform the User that it Holds the Card
		    player.setRelease_from_prison_card(true);
		    // Exit the While Loop - Turn is Over
		    isTurnOver = true;
		    //notify
		    EventArrayResult.addResults(new GameEvents(GameName, Monopol.getInstance().getEventIDCounter(), 18, player.getName(), " Get Out Of Jail Card", player.getGame_location()));
		}
	    } // End While
	} // End Card Checking
	else // The Card Received is Wrong
	{
	    throw new WrongCardType("Error! Wrong Card Type!\nExpected Surprise Card and received a " + Square_Type + " Card.\n");
	}
    }

    /**
     * This Function will Clear all the Assets of this player from there owner
     * and Delete the Player from the Players Array
     * @param deleted_player The Player to be Deleted
     * @return The Player is Ready for Deletion
     */
    public Boolean deletePlayer(Player deleted_player) {
	try {
	    // Delete the Player from the Game
	    // Delete the Players Assets
	    deleted_player.deleteAssets();
	    // Return the Players' Remaining Money back to the Cashier
	    cashier += deleted_player.getFunds();
	    // Update the Cash in the Game Cashier
	    // Verify that the Player has no more Assetes
	    if (deleted_player.getAssets().isEmpty()) {
		deleted_player.setToDelete(true);
		// Decrease the Number of Players
		decresePlayerCount();
		// Return Ready to Delete
		return true;

	    } else // Could not delete all the Players Assets
	    {
		throw new RuntimeException("Not All the Assets could be Cleared");
	    }
	} catch (Error e) {
	    // This Should never happen
	    throw new RuntimeException("Something Terrible just Happened...\n" + e.toString());
	}
    }

    public void deletePlayer(Integer ID) throws MonopolErrors {
	for (Player deletedplayer : players) {
	    if (deletedplayer.getID().equals(ID)) {
		if (!deletedplayer.getToDelete()) {
		    // Delete the Player
		    Boolean retDelete = deletePlayer(deletedplayer);
		    //create new event indecting player was deleted
		    EventArrayResult.addResults(new GameEvents(GameName, Monopol.getInstance().getEventIDCounter(), 5, deletedplayer.getName(), " Player Lost", deletedplayer.getGame_location()));
		    if (!retDelete) {
			throw new MonopolErrors("Player " + deletedplayer.getName() + " was NOT  Deleted Successfuly!");
		    }
		}

	    }

	}
    }

    public void resignPlayer(Integer ID) throws MonopolErrors {

	for (Player resignplayer : players) {
	    if (resignplayer.getID().equals(ID)) {
		if (!resignplayer.getToDelete()) {
		    // Delete the Player
		    Boolean retDelete = deletePlayer(resignplayer);
		    //create new event indecting player was deleted
		    EventArrayResult.addResults(new GameEvents(GameName, Monopol.getInstance().getEventIDCounter(), 4, resignplayer.getName(), "Player Resigned", resignplayer.getGame_location()));
		    if (!retDelete) {
			throw new MonopolErrors("Player " + resignplayer.getName() + " did NOT Resigned Successfuly!");
		    }
		}

	    }

	}
    }

    /**
     * This Function Creates an Asset Offer for Sell from the Player who wants to sell an Asset
     * @param player The Player who want to offer something to Sell
     * @return An Asset Offer for Sell
     */
    @SuppressWarnings("unchecked")
    /*public  Asset_Offer sellAsset(Player player)
    {
    // Create a temporary array for all the assets
    ArrayList<Negotiable> allAssets = new ArrayList<Negotiable>();
    // Create a temporary array for all the asset Groups
    ArrayList<AssetGroup> assetGroups = new ArrayList<AssetGroup>();
    // Create the Return Asset Array
    ArrayList<Negotiable> arrAssets = null;
    // Create the Return Asset Offer
    Asset_Offer assetOffer;

    // Go Over all the players assets and insert them into the correct array
    for (Square iAsset : player.getAssets())
    {
    // Create a Temporary Flag if to Add Only The Asset Group to the Array or Not
    Boolean addGroupOnly = false;
    // Check if all the Assets in the Group are owned by this Player
    if(iAsset.getGroup().isAllAssetGroupMine(player))
    {
    try
    {
    // Check if the State has Cities - Relevant only for Cities and States
    if(((State)iAsset.getGroup()).getIsHouseExists())
    addGroupOnly = true;
    }
    catch(ClassCastException  e)
    {
    // Do Nothing - Probably not a State Group
    }
    finally
    {
    // Check that the Asset Group Array don't have this Asset Group Already
    if(! assetGroups.contains(iAsset.getGroup()))
    {
    // Add the Asset group to the Array
    assetGroups.add(iAsset.getGroup());
    }
    }
    }
    // Check if to add the Asset to the Array or not
    if(!addGroupOnly)
    allAssets.add(iAsset);
    }
    // Check if the Player is Human
    if(player.isHuman())
    {
    // Print all the Assets for Sale and Get the Chosen Asset
    arrAssets = printAssets(allAssets, assetGroups);
    // Create the Asset Offer
    assetOffer = new Asset_Offer(player, arrAssets);
    }
    else // Player is a Computer
    {
    // Get the First Asset Available
    if(allAssets.size() != 0)
    {
    // Create a Temporary Array
    ArrayList<Negotiable> tempArray = new ArrayList<Negotiable>();
    // Add the First Asset to the Temporary Array
    tempArray.add(allAssets.get(0));
    // Set the Asset Array to the Temporary Array
    arrAssets = tempArray;
    }
    else if(assetGroups.size() != 0)
    {
    // The Warning here was on the Casting - the Casting is from ArrayList<?> to ArrayList<Negotiable>
    // We Needed to use Generics because it is Implemented in the Interface
    arrAssets = (ArrayList<Negotiable>) assetGroups.get(0).getAssets();
    }
    // Computer Returns the First Asset
    assetOffer = new Asset_Offer(player, arrAssets);
    }
    // Return the Asset Offer
    return assetOffer;
    }


    /**
     * Function Prints The Assets List For Sell
     * @param assetList The Asset List
     * @param groupList The Asset Group List
     * @return An ArrayList of the Chosen Asset (or Asset Group Assets)

    @SuppressWarnings("unchecked") */
    /*private  ArrayList<Negotiable> printAssets(ArrayList<Negotiable> assetList, ArrayList<AssetGroup> groupList)
    {
    // Print all the Assets
    for (int i = 0; i < assetList.size(); i++)
    {
    // Write the Asset Name
    Utils.writeText(((Integer)(i+1)).toString()+")", assetList.get(i).getName());
    }

    // Continue Index - Get the Size of the Asset List
    Integer assetsSize = assetList.size();//was previously  + 1 don't know why;

    // Print all the Asset Groups
    for (int i = 0; i < groupList.size(); i++)
    {
    // Write the Group Name
    Utils.writeText(((Integer)(i+assetsSize+1)).toString()+")", groupList.get(i).getName());
    }
    // Set to Null for Initialization
    Integer chosenAssetNum = null;
    // Loop until a valid number is Received
    while(chosenAssetNum == null)
    {
    try
    {
    // Get the Number from the Player
    chosenAssetNum = Integer.parseInt(Utils.readText("Choose the Index of the Asset that you Want to Sell:", true));
    // Check that player didn't input a number outside the bounds of the arrays
    if(chosenAssetNum > (assetsSize + groupList.size()))
    chosenAssetNum = null;
    }
    catch(NumberFormatException e)
    {
    Utils.writeText("Wrong Number was collected, try Again.");
    }
    }
    // Check if the Chosen asset is from the Asset Group or the Normal Assets
    if(chosenAssetNum > assetsSize)
    {
    // Must be from the Asset Group -  Return All the Assets in that Group as a Negotiable Array List
    // The Warning here was on the Casting - the Casting is from ArrayList<?> to ArrayList<Negotiable>
    // We Needed to use Generics because it is Implemented in the Interface
    return (ArrayList<Negotiable>) groupList.get(chosenAssetNum-assetsSize-1).getAssets();
    }
    else
    {
    // Must be from the Normal Assets
    // Create a Temporary Array List
    ArrayList<Negotiable> retArray = new ArrayList<Negotiable>();
    // Add the Asset that we want to sell to the array
    retArray.add(assetList.get(chosenAssetNum-1));
    // Return the Asset
    return retArray;
    }
    }*/
    /**
     * This Function Checks and Sells Assets for the Player in order to Gain the Amount of Money Needed.
     * @param player The Player that Needs Checking
     * @param money2Gain The Amount of money the Player needs to Gain
     * @throws NoAssets
     * @throws PlayerQuits
     * @throws PlayerForcedtoQuit
     */
    public void checkMoneyandAssets(Player player, Double money2Gain) throws NoAssets, PlayerQuits, PlayerForcedtoQuit {
	// In order to count the Number of Sales
	Integer num_of_sales = 0;
	/*// Check if the player is not marked for deletion
	if(!player.getToDelete())
	{
	// Check that the Player has Assets
	if(player.getAssets().size() != 0)
	{
	Boolean sellAssets;
	// Check that the player is Human
	if(player.isHuman())
	{
	// Check if the Player wants to sell its Assets or Quit the Game
	sellAssets = Utils.showPlayerDialog("You need to pay " + money2Gain +".\nDo you want to sell some of your assets? (Answering 'No' will Force you to Quit the Game)");
	}
	else // Player is a Computer
	// Always try to sell assets
	sellAssets = true;
	if(sellAssets)
	{
	// Loop while the Player does not have enough money
	while(player.getFunds() <= money2Gain && num_of_sales < NUMBER_OF_ALLOWED_AUCTION)
	{
	// Auction out the Player Assets and
	// Add the Earnings from the Sell to the Players Funds
	auctionAssets(player);
	//counts the number of actions initiated by player
	num_of_sales++;
	// Check if the Player gained the money it needs
	if(player.getFunds() < money2Gain)
	Utils.writeText("You still haven't got enough money, sell more assets");
	// Check if the Player offered to much offers
	if(num_of_sales >= NUMBER_OF_ALLOWED_AUCTION && player.getFunds() < money2Gain)
	{
	// No Money, No Assets, No Game!
	Utils.writeText("You Exceeded the number of allowed offers, and you dont have enough money.\n" +
	"You are Forced to quit the game");
	}
	}
	}
	else if (!sellAssets) // Player wants to Quit the Game
	throw new PlayerQuits();
	}
	else
	{
	// Player does not have Any Assets
	throw new NoAssets();
	}*/
	// Check if the Player didn't gained to required money or
	// exceeded the number of allowed offers
	// The Game Forces the Player to Quit
	if (player.getFunds() < money2Gain || num_of_sales > NUMBER_OF_ALLOWED_AUCTION) {
	    throw new PlayerForcedtoQuit();
	} //}
	else {
	    // The Player is Marked for Deletion, Ignore It
	}
    }

    /**
     * Function to Auction the Players' Assets.
     * Player is able to choose its best offer and sell it to that player.
     * @param player The Player that wants to Auction his Assets
     * @throws NoAssets
     */
    /*public  void auctionAssets(Player player) throws NoAssets
    {
    // Check that the Player has Assets
    if(player.getAssets().size() != 0)
    {
    // Get the Asset to Sell Offer
    Asset_Offer assetToSell = sellAsset(player);
    // Get the Next Player Location in the Array
    Integer playerIndex = players.indexOf(player);
    // Create an Array of the other Players Offerings
    ArrayList<Offer> arrOffers = new ArrayList<Offer>();
    // Loop all the Players beginning from the next player until the current player
    for(Integer nextPlayer = playerIndex + 1; (nextPlayer%players.size()) != playerIndex ; nextPlayer++)
    {
    // Create an Offer Variable
    Offer offer = null;
    // Bind to the Next Players' Object
    Player p = players.get((nextPlayer%players.size()));
    // Double Check - Don't Ask the Player who is Selling
    if(p != player)
    {
    if(p.isHuman())
    {
    try
    {
    // Ask the Player if it wants to make an Offer for the Asset
    Integer ans = Integer.parseInt(Utils.readText("Player "+player.getName()+" Is offering "+assetToSell.getName()+"\n"+p.getName()+":"+
    "Do you want to offer Money or an Asset in Exchange?\n" +
    "1)Money\n2)Asset\n3)Dont Offer\nAnswer: ", true));
    // Check player offer (Money or Asset)
    if(ans == 1) // Player wants to offer Money
    {
    // Ask the Player how much money it wants to offer
    Double  moneyOffer = Double.parseDouble(Utils.readText(p.getName() + ", How much do you want to offer on this Asset? ", true));
    while (moneyOffer>p.getFunds())//while offers are invalid
    {
    Utils.writeText(p.getName()," can offer up to",p.getFunds().toString());
    moneyOffer = Double.parseDouble(Utils.readText(p.getName() + ", How much do you want to offer on this Asset? ", true));
    }
    // Create the Money Offer
    offer = new Money_offer(p, moneyOffer);
    }
    else if(ans == 2) // Player wants to offer an asset
    {
    // Check players assets
    if(player.getAssets().size() != 0)
    {
    // Get the Asset to Sell Offer
    offer = sellAsset(p);
    }
    else // Player doesn't have any Assets
    {
    Utils.writeText("You don't have any assets, your offer is ignored.");
    }
    }
    else if(ans == 3) // Player is not offering
    {
    // No Offer is Taken
    offer = null;
    }
    }
    catch(NumberFormatException e)
    {
    Utils.writeText("No number was Collected, your Offer is ignored.");
    }
    }
    else // Player is a Computer
    {
    // Check that Player has Enough Money to Offer
    if(p.getFunds() > assetToSell.getAssetOffer().get(0).getCost() + 100)
    {
    // Offer a New Money Offer
    offer = new Money_offer(p, (assetToSell.getAssetOffer().get(0).getCost() + 100));
    }
    else
    {
    // Do not offer anything
    }

    }
    // Check that the Player offered something and add to the Array
    if(offer != null)
    arrOffers.add(offer);
    }
    } // End For
    Offer chosenOffer = null;
    // Check that there are Offers on that Asset
    if(arrOffers.size() != 0)
    {
    // Check if the Player is Human
    if (player.isHuman())
    {
    // Print the Offers for the Selling Player to Choose from
    chosenOffer = printOffers(arrOffers);
    }
    else // Player is Computer
    {
    //if player is not human first offer will be selected
    chosenOffer = arrOffers.get(0);
    }
    }
    else
    {
    // No Offers were made, Ask player to Mortgage his Asset to the Game
    Boolean sellToGame = false;
    // Check if Player is Human
    if(player.isHuman())
    {
    // Ask the Player if it want to Mortgage its Asset
    sellToGame = Utils.showPlayerDialog("Do You want to Mortgage your Asset?");
    }
    else // Player is Computer
    sellToGame = true; // Always Sell To Game
    // Check Player Answer
    if(sellToGame)
    {
    // Players wants to Sell to Game
    chosenOffer = new Money_offer(null, assetToSell.getAssetOffer().get(0).getCost());
    }
    }
    // Finalize the Auction
    // Check that the Chosen Offer is Not Null
    if(chosenOffer != null)
    {
    handleOffers(assetToSell, chosenOffer);
    // Check that the Buying Player is not NULL
    if(chosenOffer.getPlayer() != null)
    {
    // Check Offer Type
    if(chosenOffer.getOfferType() == OfferType.ASSET_OFFER)
    {
    // Inform Other Users on the Deal - An Asset Exchange
    Utils.writeText(assetToSell.getPlayer().getName(),"Sold", assetToSell.getName(),"to",chosenOffer.getPlayer().getName(),"in Exchange for",((Asset_Offer)chosenOffer).getName(),"\n");
    }
    else
    {
    // Inform Other Users on the Deal - An Asset Sell
    Utils.writeText(assetToSell.getPlayer().getName(),"Sold", assetToSell.getName(),"to",chosenOffer.getPlayer().getName(),"for the price of",((Money_offer)chosenOffer).getMoneyOffer().toString(),"\n");
    }
    }
    else
    {
    // Inform Other Users on the Deal
    Utils.writeText(assetToSell.getPlayer().getName(),"Mortagaged", assetToSell.getName(),"for the price of",((Money_offer)chosenOffer).getMoneyOffer().toString(),"\n");
    }
    }
    else
    {
    // No Deal was Done
    }
    } // End Asset Check
    else
    {
    // Player does not have any assets
    // "Player " + player.getName() + " Has no Assets to Sell!"
    throw new NoAssets();
    }
    }*/
    /**
     * Function Prints out the Offers and Let the Player Choose what Offer he Wants
     * @param arrOffers The Offers Array
     * @return The Desired Offer or Null if no Offer was Selected
     */
    /*private  Offer printOffers(ArrayList<Offer> arrOffers)
    {
    Offer retOffer = null;
    // Print all the Assets
    for ( int i = 0; i < arrOffers.size(); i++)
    {
    // Write the Offer Details
    Utils.writeText(((Integer)(i+1)).toString()+")", arrOffers.get(i).toString());
    }
    // Add an Option to exit
    Utils.writeText(((Integer)(arrOffers.size()+1)).toString() + ")", "None of these offers");

    try
    {
    Integer chosenOfferNum = Integer.parseInt(Utils.readText("Choose the Index of the Offer that you Want: ", true));
    // Check if player doesn't want any of these offers
    if(chosenOfferNum >= (arrOffers.size()+1))
    retOffer = null;
    else
    // Get the Chosen Offer
    retOffer = arrOffers.get(chosenOfferNum-1);
    }
    catch(NumberFormatException e)
    {
    // Print out the Error Message
    Utils.writeText(e.getMessage());
    // Set Offer to Null
    retOffer = null;
    }
    catch(IndexOutOfBoundsException e)
    {
    // Print out the Error Message
    Utils.writeText("You Entered a Number out side the specified indexes.\nYour request is ignored.");
    // Set offer to Null
    retOffer = null;
    }
    // Return the Offer
    return retOffer;
    }*/
    /**
     * Function will handle the Offers given.
     * If the Asset To Get is Money, the function Changes Owners on the Asset being sold and Gets the Money.
     * If the Asset To Get is Another Asset, the function Switches ownership on those Assets.
     * @param assetToGive An Asset Offer - an Asset to Sell
     * @param assetToGet Can be Money Offer or Asset Offer in Exchange for the Asset being Sold
     */
    /*public  void handleOffers(Offer assetToGive, Offer assetToGet)
    {
    // Gets the selling player
    Player sell_player = assetToGive.getPlayer();
    //gets the buying player
    Player buy_player = assetToGet.getPlayer();
    //gets the asset/s that were sold
    ArrayList<Negotiable>sold_assets=((Asset_Offer)assetToGive).getAssetOffer();
    try{
    // swap owners
    for(Negotiable asset:sold_assets)
    {
    //removes the sold assets
    sell_player.getAssets().remove(asset);
    //sets new owner
    asset.setOwner(buy_player);
    // Check that the Buying Player is not the Game (Null)
    if(buy_player != null)
    // Adds new asset to player
    buy_player.getAssets().add((Square)asset);

    }
    // Check if the Offer is Money or Asset
    if (assetToGet.getOfferType() == OfferType.MONEY_OFFER)
    {
    // Gets the offer made by player
    Double offer =((Money_offer)assetToGet).getMoneyOffer();
    // Adds funds to the sell player
    sell_player.addFunds(offer);
    // Check that the Buying Player is not the Game (Null)
    if(buy_player != null)
    // Reduce funds from buyer
    buy_player.addFunds(-1*offer);
    else
    {
    // Take money from the cashier
    cashier -= offer;
    // Update the Cash in the Game Cashier
    }
    }
    else // Offer is an Asset
    {
    // Gets the swapped assets
    ArrayList<Negotiable>swap_assets=((Asset_Offer)assetToGet).getAssetOffer();
    for (Negotiable swap_asset:swap_assets)
    {
    //removes the sold assets
    buy_player.getAssets().remove(swap_asset);
    //sets new owner
    swap_asset.setOwner(sell_player);
    //adds new asset to player
    sell_player.getAssets().add((Square)swap_asset);
    }
    }
    }
    catch(Error e)
    {
    // This shouldn't have Happened...
    throw new RuntimeException("Something terrible just happened.\n" + e.toString());
    }
    }*/
    /**
     * This Function Initializes the Cards and Squares
     * And sets each player in a position to start the Game
     */
    private void initGame() {
	// Get the Resource Path in th eProject
	URL path = getClass().getClassLoader().getResource("resources/monopoly_config.xml");
	// Parse the Configuration File
	MonopolyXML monopolyParser = new MonopolyXML(path);
	if (monopolyParser.getParseOK()) {
	    // Get the Warning Cards Deck
	    warning_cards = monopolyParser.getWarningDeck();
	    // Shuffle the Cards
	    Collections.shuffle(warning_cards);
          //warning_cards.set(0,  warning_cards.get(2));
	    // Get the Surprise Cards Deck
	    surprise_cards = monopolyParser.getSurpriseDeck();
	    // Shuffle the Cards
	   Collections.shuffle(surprise_cards);
	    // Get all the Transportations
	    transportations = monopolyParser.getAllTransportaions();
	    // Get all the Services
	    services = monopolyParser.getAllServices();
	    // Get the Squares Order
	    squares = monopolyParser.getSquaresOrder();
	} else {
	    // Initialize the Game Squares
	    squares = new Square[36]; // Set the Number of Squares
	    transportations = new AllTransportations(); // Create the Transportation Group
	    services = new AllServices(); // Create the Services Group
	    // Create the Squares
	    squares[fixedSquares.START_SQUARE.get()] = new Square("Start");
	    Double[] stay_price = Utils.createDoubleArray((double) 250, (double) 300, (double) 350, (double) 400);
	    states = new State[8];
	    states[0] = new State("Canada", Color.pink);
	    squares[1] = states[0].CreateCity("Montreal", stay_price, new Double(300), new Double(100));
	    squares[2] = states[0].CreateCity("Toronto", stay_price, new Double(400), new Double(50));
	    squares[3] = new Square("Surprise");
	    states[1] = new State("England", Color.blue);
	    Double[] trans_stay_price = Utils.createDoubleArray((double) 10, (double) 15);
	    squares[4] = transportations.createTransportation("Dan", trans_stay_price, new Double(100));
	    squares[5] = states[1].CreateCity("London", stay_price, new Double(600), new Double(100));
	    squares[6] = states[1].CreateCity("Manchester", stay_price, new Double(350), new Double(25));
	    squares[7] = states[1].CreateCity("Liverpool", stay_price, new Double(300), new Double(15));
	    squares[8] = new Square("Warning");
	    squares[fixedSquares.PRISON_SQUARE.get()] = new Square("Prison");
	    states[2] = new State("Spain", Color.yellow);
	    squares[10] = states[2].CreateCity("Madrid", stay_price, new Double(550), new Double(75));
	    squares[11] = states[2].CreateCity("Valencia", stay_price, new Double(350), new Double(20));
	    squares[12] = states[2].CreateCity("Barcelona", stay_price, new Double(500), new Double(80));
	    Double[] service_stay_price = Utils.createDoubleArray((double) 20, (double) 30);
	    squares[13] = services.createService("Electricity CO.", service_stay_price, new Double(120));
	    squares[14] = transportations.createTransportation("Egged", trans_stay_price, new Double(100));
	    states[3] = new State("Germany", Color.black);
	    squares[15] = states[3].CreateCity("Berlin", stay_price, new Double(550), new Double(75));
	    squares[16] = states[3].CreateCity("Munich", stay_price, new Double(350), new Double(20));
	    squares[17] = states[3].CreateCity("Hamburg", stay_price, new Double(500), new Double(80));
	    squares[fixedSquares.PARKING_SQUARE.get()] = new Square("Parking");
	    states[4] = new State("Italy", Color.green);
	    squares[19] = states[4].CreateCity("Milan", stay_price, new Double(550), new Double(75));
	    squares[20] = states[4].CreateCity("Bologna", stay_price, new Double(350), new Double(20));
	    squares[21] = states[4].CreateCity("Roma", stay_price, new Double(500), new Double(80));
	    squares[22] = new Square("Warning");
	    squares[23] = transportations.createTransportation("Kavim", trans_stay_price, new Double(100));
	    states[5] = new State("China", Color.red);
	    squares[24] = states[5].CreateCity("Beijing", stay_price, new Double(425), new Double(33));
	    squares[25] = states[5].CreateCity("Shanghai", stay_price, new Double(350), new Double(26));
	    squares[26] = states[5].CreateCity("Hong kong", stay_price, new Double(430), new Double(50));
	    squares[fixedSquares.GO2PRISON_SQUARE.get()] = new Square("Go to Prison");
	    states[6] = new State("Israel", Color.magenta);
	    squares[28] = states[6].CreateCity("Tel aviv", stay_price, new Double(550), new Double(100));
	    squares[29] = states[6].CreateCity("Haifa", stay_price, new Double(500), new Double(90));
	    squares[30] = states[6].CreateCity("Jerusalem", stay_price, new Double(520), new Double(95));
	    squares[31] = services.createService("Bezeq", service_stay_price, new Double(70));
	    squares[32] = transportations.createTransportation("El-Al", trans_stay_price, new Double(150));
	    states[7] = new State("USA", Color.cyan);
	    squares[33] = states[7].CreateCity("New york", stay_price, new Double(610), new Double(100));
	    squares[34] = states[7].CreateCity("Chicago", stay_price, new Double(500), new Double(90));
	    squares[35] = states[7].CreateCity("Los angeles", stay_price, new Double(570), new Double(95));

	    // Initializing the Cards
	    //3 types of warning cards 1.go to prison ,2.go to next warning square ,3.pay
	    warning_cards = new ArrayList<Card>();
	    warning_cards.add(new Move_card(CardType.WARNING_CARD, "Go to prison", eGoTo.PRISON));
	    warning_cards.add(new Move_card(CardType.WARNING_CARD, "Go to prison", eGoTo.PRISON));
	    warning_cards.add(new Move_card(CardType.WARNING_CARD, "Go to prison", eGoTo.PRISON));
	    warning_cards.add(new Move_card(CardType.WARNING_CARD, "Go to next warning square", eGoTo.NEXT_WARNING));
	    warning_cards.add(new Move_card(CardType.WARNING_CARD, "Go to next warning square", eGoTo.NEXT_WARNING));
	    warning_cards.add(new Move_card(CardType.WARNING_CARD, "Go to next warning square", eGoTo.NEXT_WARNING));//need to edit move card
	    warning_cards.add(new Money_card(CardType.WARNING_CARD, "Pay 500 to Cashire", new Double(100), new Boolean(true)));
	    warning_cards.add(new Money_card(CardType.WARNING_CARD, "Pay 700 to Players", new Double(70), new Boolean(false)));
	    warning_cards.add(new Money_card(CardType.WARNING_CARD, "Pay 100 to Players", new Double(10), new Boolean(false)));//trick card doesn't do as tells
	    // Shuffle the Cards
	    Collections.shuffle(warning_cards);
	    //4 types of surprise_cards 1.go to start,2.go to next surprise square,3.get money 4.get out of prison
	    surprise_cards = new ArrayList<Card>();
	    surprise_cards.add(new Card(CardType.SURPRISE_CARD, "Get out of prison"));
	    surprise_cards.add(new Move_card(CardType.SURPRISE_CARD, "Go to start", eGoTo.START));
	    surprise_cards.add(new Move_card(CardType.SURPRISE_CARD, "Go to start", eGoTo.START));
	    surprise_cards.add(new Move_card(CardType.SURPRISE_CARD, "Go to next surprise square", eGoTo.NEXT_SURPRISE));
	    surprise_cards.add(new Move_card(CardType.SURPRISE_CARD, "Go to next surprise square", eGoTo.NEXT_SURPRISE));
	    surprise_cards.add(new Move_card(CardType.SURPRISE_CARD, "Go to next surprise square", eGoTo.NEXT_SURPRISE));
	    surprise_cards.add(new Money_card(CardType.SURPRISE_CARD, "Get 500", new Double(500), new Boolean(true)));
	    surprise_cards.add(new Money_card(CardType.SURPRISE_CARD, "Get 700 from players", new Double(70), new Boolean(false)));
	    surprise_cards.add(new Money_card(CardType.SURPRISE_CARD, "Get 100 from players", new Double(10), new Boolean(false)));//trick card doesn't do as tells
	    // Shuffle the Cards
	    Collections.shuffle(surprise_cards);
	}
    }

    /**
     * This Function Loads the Monopoly Players
     */
    /**
     * Returns the Square Name of the Players Location
     * @param location The Current Player Location
     * @return The Name of the Square the Player is at
     */
    public String getSquareName(Integer location) {
	return squares[location].getName();
    }

    /**
     * Check if a Player passed the Start Square and does it need to get paid
     * @param prevLocation The Previous Player Location
     * @param currLocation The Current Player Location
     * @return The Amount the Game Needs to Play the Player
     */
    public Double checkGo2Start(Integer prevLocation, Integer currLocation, String player_name) {
	if (cashier > 0) {
	    // Check if The Player went pass the Start Square
	    if (prevLocation > currLocation) {
		// Check if the Player is ON the Start Square
		if (currLocation == 0) {
		    // Inform that the Player got 400 Shekels
		    EventArrayResult.addResults(new GameEvents(GameName, Monopol.getInstance().getEventIDCounter(), 10, player_name, "  Landed on Start Square", currLocation));
		    EventArrayResult.addResults(new PaymentEvents(GameName, Monopol.getInstance().getEventIDCounter(), 19, player_name, " Payment", currLocation, true, false, null, 400));
		    // Reduce 400 Shekels from the Cashier
		    cashier -= 400;
		    // Update the Cash in the Game Cashier
		    // Return the Player 400 Shekels for Standing on the Start Square
		    return 400.0;
		} else {
		    // Inform that the Player got 200 Shekels
		    EventArrayResult.addResults(new GameEvents(GameName, Monopol.getInstance().getEventIDCounter(), 9, player_name, "  Passed Start Square", currLocation));
		    EventArrayResult.addResults(new PaymentEvents(GameName, Monopol.getInstance().getEventIDCounter(), 19, player_name, "   Payment", currLocation, true, false, null, 200));

		    // Reduce 200 Shekels from the Cashier
		    cashier -= 200;
		    // Update the Cash in the Game Cashier
		    // Return the Player 200 Shekels for Passing the Start Square
		    return 200.0;
		}
	    } else // Player did not pass the Start Square
	    {
		return 0.0;
	    }
	} else // No Money in the Cashier
	// no event was created
	{
	    return 0.0;
	}

    }

    /**
     * Remove player from counted players
     */
    public void decresePlayerCount() {
	numOfPlayingPlayers--;
    }

    /**
     * Returns the Game Name
     */
    public String getGameName() {
	return GameName;
    }
}
